package com.cloudm.technician.di

import android.content.Context
import com.cloudm.technician.BuildConfig
import com.cloudm.technician.data.config.Config
import com.cloudm.technician.data.preferences.PreferencesHelper
import com.cloudm.technician.extensions.isConnected
import com.facebook.stetho.okhttp3.StethoInterceptor
import dagger.Module
import dagger.Provides
import okhttp3.*
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import javax.inject.Named
import javax.inject.Singleton

/**
 * 作者: wesley
 * 时间: 2017/11/20
 * 描述: 提供retrofit实例
 */
@Module(includes = [(DbPreferencesModule::class)])
class NetworkModule(private val context: Context) {

    /**
     * 提供retrofit 实例
     */
    @Singleton
    @Provides
    fun provideRetrofit(baseUrl: String, okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder().baseUrl(baseUrl).client(okHttpClient).addConverterFactory(
                GsonConverterFactory.create()).addCallAdapterFactory(
                RxJava2CallAdapterFactory.create()).build()
    }


    /**
     * 提供retrofit 实例
     */
    @ForCloudm
    @Singleton
    @Provides
    fun provideRetrofitForCloudm(@ForCloudm baseUrl: String, okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder().baseUrl(baseUrl).client(okHttpClient).addConverterFactory(
                GsonConverterFactory.create()).addCallAdapterFactory(
                RxJava2CallAdapterFactory.create()).build()
    }


    /**
     * 提供retrofit 实例
     */
    @ForUploadPic
    @Singleton
    @Provides
    fun provideRetrofitForUploadPic(@ForUploadPic baseUrl: String,
                                    okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder().baseUrl(baseUrl).client(okHttpClient).addConverterFactory(
                GsonConverterFactory.create()).addCallAdapterFactory(
                RxJava2CallAdapterFactory.create()).build()
    }


    /**
     * 提供baseUrl 实例
     */
    @Singleton
    @Provides
    fun provideBaseUrl() = Config.baseUrl


    /**
     * 提供baseUrl 实例
     */
    @ForCloudm
    @Singleton
    @Provides
    fun provideBaseUrlForCloudm() = Config.baseUrlForCloudm


    /**
     * 提供baseUrl 实例
     */
    @ForUploadPic
    @Singleton
    @Provides
    fun provideBaseUrlForUploadPic() = Config.baseUrlForUploadPic


    @Singleton
    @Provides
    fun provideOkHttpClient(httpLoggingInterceptor: HttpLoggingInterceptor, cache: Cache, @Named(
            "cache_interceptor") cacheInterceptor: Interceptor, @Named(
            "parameter_interceptor") parameterInterceptor: Interceptor): OkHttpClient {
        return OkHttpClient.Builder().cache(cache).addInterceptor(
                httpLoggingInterceptor).addInterceptor(cacheInterceptor).addInterceptor(
                parameterInterceptor).addNetworkInterceptor(cacheInterceptor).addNetworkInterceptor(
                StethoInterceptor()).build()
    }


    @Singleton
    @Provides
    fun provideHttpLoggingInterceptor(): HttpLoggingInterceptor {
        return HttpLoggingInterceptor().apply {
            level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
        }
    }


    @Singleton
    @Provides
    fun provideCache(): Cache {
        val cacheFile = File(context.externalCacheDir, "cache_network_auxiliarytool")
        return Cache(cacheFile, 50 * 1024 * 1024)
    }


    @Named("cache_interceptor")
    @Singleton
    @Provides
    fun provideCacheInterceptor(): Interceptor {
        return Interceptor { chain ->
            var request = chain.request()
            if (!context.isConnected()) {
                request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build()
            }
            var response: okhttp3.Response = chain.proceed(request)
            response = if (context.isConnected()) {
                val cacheControl: CacheControl = request.cacheControl()
                val value = cacheControl.toString()
                val noCache = "public, max-age=" + 0
                response.newBuilder().header("Cache-Control",
                        if (value.trim().isEmpty()) noCache else value).build()
            } else {
                response.newBuilder().header("Cache-Control",
                        "public, only-if-cached, max-stale=" + 24 * 60 * 60 * 7).build()
            }
            response
        }
    }


    @Named("parameter_interceptor")
    @Singleton
    @Provides
    fun provideParamInterceptor(presencesHelper: PreferencesHelper): Interceptor {
        return Interceptor { chain ->
            val request: Request
            val originalRequest = chain.request()
            val method = originalRequest.method()
            val token = presencesHelper.token ?: ""
            when (method) {
                "GET" -> {
                    val builder = originalRequest.url().newBuilder()
                    val newHttpUrl: HttpUrl
                    newHttpUrl = builder.addQueryParameter("token", token).build()
                    request = originalRequest.newBuilder().url(newHttpUrl).build()
                    chain.proceed(request)
                }
                "POST" -> {
                    val body = originalRequest.body()
                    body as? FormBody ?: chain.proceed(originalRequest)
                    val formBuilder = FormBody.Builder()
                    val formBody: FormBody
                    val size = (body as FormBody).size()
                    for (i in 0 until size) {
                        val name = body.name(i)
                        val value = body.value(i)
                        formBuilder.add(name, value)
                    }
                    formBody = formBuilder.add("token", token).build()
                    request = originalRequest.newBuilder().post(formBody).build()
                    chain.proceed(request)
                }
                else -> chain.proceed(originalRequest)
            }
        }
    }
}